#pragma once
#include <iostream>
#include <string>
#include <string.h>
#include <vector>
#include <fstream>
#include <sys/types.h>
#include <sys/stat.h>
#include <experimental/filesystem>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "log.hpp"
namespace RBC
{
    namespace fs = std::experimental::filesystem;
    class FileUtil
    {
    public:
        FileUtil(const std::string& filename)
            : _filename(filename)
        {
        }
        size_t FileSize() // 获取文件大小
        {
            struct stat st;
            memset(&st, 0, sizeof st);
            int ret = stat(_filename.c_str(), &st);
            if (ret < 0)
            {
                logMassage(ERROR, "获取文件大小失败：[%d][%s]\n", errno, strerror(errno));
                return -1;
            }
            return st.st_size;
        }
        time_t LastMTime() // 获取文件最后一次修改时间
        {
            struct stat st;
            memset(&st, 0, sizeof st);
            int ret = stat(_filename.c_str(), &st);
            if (ret < 0)
            {
                logMassage(ERROR, "获取文件最终修改时间失败：[%d][%s]\n", errno, strerror(errno));
                return -1;
            }
            return st.st_mtime;
            
        }
        time_t LastATime() // 获取文件最后一次访问时间
        {
            struct stat st;
            memset(&st, 0, sizeof st);
            int ret = stat(_filename.c_str(), &st);
            if (ret < 0)
            {
                logMassage(ERROR, "获取文件最终访问时间失败：[%d][%s]\n", errno, strerror(errno));
                return -1;
            }
            return st.st_atime;
        }

        std::string FileName() // 获取路径中的纯文件名称
        {
            size_t pos = _filename.find_last_of("\\");
            if (pos == std::string::npos)
            {
                return _filename;
            }
            return _filename.substr(pos + 1);
        }

        bool GetPosLen(std::string* body, size_t pos, size_t len) // 获取文件指定位置，指定长度的数据
        {
            // 先判断你从指定位置读取的指定长度超没超过文件大小，超过了直接返回错误
            size_t filesz = FileSize();
            if (pos + len > filesz)
            {
                logMassage(ERROR, "输入参数不合法！超出文件大小\n");
                return false;
            }
            std::ifstream ifs;
            ifs.open(_filename, std::ios::binary);
            if (ifs.is_open() == false)
            {
                logMassage(ERROR, "读取文件时打开文件失败：[%d][%s]\n", errno, strerror(errno));
                return false;
            }
            ifs.seekg(pos, std::ios::beg); // 从文件起始跳转到pos位置
            body->resize(len);
            ifs.read(&(*body)[0], len);
            if (ifs.good() == false)
            {
                logMassage(ERROR, "读取文件内容失败\n");
                ifs.close();
                return false;
            }
            ifs.close();
            return true;
        }
        bool GetContent(std::string* body) // 读取文件数据
        {
            if (Exists() == false)
            {
                std::string body = "";
                SetContent(&body);
            }
            size_t fsize = FileSize();
            return GetPosLen(body, 0, fsize);
        }
        bool SetContent(const std::string* body)
        {
            std::ofstream ofs;
            ofs.open(_filename, std::ios::binary);
            if (ofs.is_open() == false)
            {
                logMassage(ERROR, "写入文件时打开文件失败：[%d][%s]\n", errno, strerror(errno));
                return false;
            }
            ofs.write(&(*body)[0], (*body).size());
            if (ofs.good() == false)
            {
                logMassage(ERROR, "写入文件内容失败\n");
                ofs.close();
                return false;
            }
            ofs.close();
            return true;
        }

        bool Remove(const std::string& filename) //删除指定文件
        {
            if (fs::exists(filename) == false)
            {
                return true;
            }
            remove(filename.c_str());
            return true;
        }
        bool Remove() // 删除本文件
        {
            remove(_filename.c_str());
            return true;
        }
        bool Exists() // 判断目录是否存在 不存在就创建
        {
            return fs::exists(_filename);
        }
        bool CreateDirectory() // 创建目录
        {
            if (fs::exists(_filename))
            {
                return true;
            }
            return fs::create_directories(_filename);
        }
        bool ScanDirectory(std::vector<std::string>* arry) // 遍历目录将得到的所有文件放在一个数组中返回
        {
            CreateDirectory();
            for (auto& p : fs::directory_iterator(_filename))
            {
                if (fs::is_directory(p))
                    continue;
                arry->push_back(fs::path(p).relative_path().string());
            }
            return true;
        }
    private:
        std::string _filename;
    };
}